﻿using NICWebApi.Extensions.DynamicAPI.Conventions;
using NICWebApi.Extensions.DynamicAPI.Options;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// 动态WebApi扩展类
/// </summary>
public static class DynamicWebApiExtensions
{
    #region 原始实现 - 简单重载方法
    // 不足：代码重复，两个重载方法内部逻辑几乎相同
    // public static IMvcBuilder AddDynamicWebApi(this IMvcBuilder builder)
    // {
    //     if (builder == null)
    //     {
    //         throw new ArgumentException(nameof(builder));
    //     }
    //
    //     builder.Services.AddDynamicWebApi();
    //
    //     return builder;
    // }
    //
    // public static IServiceCollection AddDynamicWebApi(this IServiceCollection services)
    // {
    //     var partManager = services.FirstOrDefault(s => s.ServiceType == typeof(ApplicationPartManager))?.ImplementationInstance as ApplicationPartManager
    //         ?? throw new InvalidOperationException($"`{nameof(AddDynamicWebApi)}` must be invoked after `{nameof(MvcServiceCollectionExtensions.AddControllers)}`.");
    //
    //     partManager.FeatureProviders.Add(new ApplicationServiceControllerFeatureProvider());
    //
    //     // 配置MvcOptions，添加自定义的约定
    //     services.Configure<MvcOptions>(options =>
    //     {
    //         // 将控制器下的action进行特性处理
    //         options.Conventions.Add(new ControllerModelConvention());
    //
    //         // 使用服务提供者创建ApplicationServiceConvention实例
    //         var serviceProvider = services.BuildServiceProvider();
    //         options.Conventions.Add(new ApplicationServiceConvention(serviceProvider));
    //     });
    //
    //     // 获取配置
    //     var options = Utils.GetOptions();
    //
    //     // 注入配置
    //     services.AddSingleton(options);
    //
    //     // 添加MiniProfiler服务，获取配置选项
    //     services.AddSwaggerWithOptions();
    //
    //     // 添加MiniProfiler服务，获取配置选项
    //     services.AddMiniProfilerWithOptions();
    //
    //     return services;
    // }
    #endregion

    /// <summary>
    /// 添加动态API
    /// </summary>
    /// <param name="builder">MVC构建器</param>
    /// <returns>MVC构建器</returns>
    /// <exception cref="ArgumentException">builder为null时抛出</exception>
    public static IMvcBuilder AddDynamicWebApi(this IMvcBuilder builder)
    {
        if (builder == null)
        {
            throw new ArgumentException(nameof(builder));
        }

        builder.Services.AddDynamicWebApi();

        return builder;
    }

    /// <summary>
    /// 添加动态API
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    /// <exception cref="InvalidOperationException">未先调用AddControllers时抛出</exception>
    public static IServiceCollection AddDynamicWebApi(this IServiceCollection services)
    {
        return services.AddDynamicWebApi(null);
    }

    /// <summary>
    /// 添加动态API
    /// </summary>
    /// <param name="builder">MVC构建器</param>
    /// <param name="action">配置选项的委托</param>
    /// <returns>MVC构建器</returns>
    /// <exception cref="ArgumentException">builder为null时抛出</exception>
    public static IMvcBuilder AddDynamicWebApi(this IMvcBuilder builder, Action<DynamicApiOptions>? action = null)
    {
        if (builder == null)
        {
            throw new ArgumentException(nameof(builder));
        }

        builder.Services.AddDynamicWebApi(action);

        return builder;
    }

    /// <summary>
    /// 添加动态API
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="action">配置选项的委托</param>
    /// <returns>服务集合</returns>
    /// <exception cref="InvalidOperationException">未先调用AddControllers时抛出</exception>
    public static IServiceCollection AddDynamicWebApi(this IServiceCollection services, Action<DynamicApiOptions>? action = null)
    {
        // 验证是否已添加ApplicationPartManager
        var partManager = services.FirstOrDefault(s => s.ServiceType == typeof(ApplicationPartManager))?.ImplementationInstance as ApplicationPartManager
            ?? throw new InvalidOperationException($"`{nameof(AddDynamicWebApi)}` must be invoked after `{nameof(MvcServiceCollectionExtensions.AddControllers)}`.");

        // 添加控制器特性提供程序
        partManager.FeatureProviders.Add(new ApplicationServiceControllerFeatureProvider());

        // 获取配置
        var options = Utils.GetOptions();

        // 应用自定义配置
        action?.Invoke(options);

        // 注册配置为单例服务
        services.TryAddSingleton(options);

        // 配置MVC选项
        services.Configure<MvcOptions>(mvcOptions =>
        {
            // 添加控制器模型约定
            mvcOptions.Conventions.Add(new ControllerModelConvention());

            // 创建应用服务约定
            // 注意：避免在配置回调中调用BuildServiceProvider，这可能导致服务范围验证问题
            var serviceProvider = services.BuildServiceProvider();
            mvcOptions.Conventions.Add(new ApplicationServiceConvention(serviceProvider));
        });

        // 添加Swagger服务
        services.AddSwaggerWithOptions();

        // 添加MiniProfiler服务
        services.AddMiniProfilerWithOptions();

        return services;
    }
}
